//////////////////////////////////////////////////////////////////////
//!\file FileSystemManager.cpp
//!\brief Does filesearch and all other file processings in a separate thread.
//!\author timmsusa@googlemail.com
//////////////////////////////////////////////////////////////////////

#include "FileSystemManager.hpp"

#include "Album.hpp"
#include <QMessageBox>
#include <QDebug>
#include <QDirIterator>
#include "Utils.hpp"


FileSystemManager::FileSystemManager(QObject *parent) :
    QObject(parent),
    m_Persistence(),
    m_DeepScanEnabled(m_Persistence.getEnableDeepScan()),
    // m_pFileStorage(new FileStorageWorkData(QDir::currentPath() + "//testData.dat")),
    m_DiffCollection(),
    m_FilesToCopyCount(),
    m_pScannerMusicCollection(),
    m_pScannerUpdateCollection()
{

}

FileSystemManager::~FileSystemManager()
{
    //delete m_pFileStorage;
}

void FileSystemManager::copyOverwrite(bool isFile, QString source, QString dest)
{
    qDebug() << "FileSystemManager::copyOverwrite";

    if ( source.isEmpty() || dest.isEmpty() )
    {
        emit sigCopyProgress(-1);
        return;
    }

    //int cnt=0;

    // Copy file or folder.
    if (isFile)
    {
        if (QFile(dest).exists())
        {
            if (!QFile::remove(dest))
            {
                // remove went wrong
                emit sigCopyProgress(-1);

                // shut up and go!
                return;
            }
        }

        if ( QFile::copy(source, dest))
        {
            emit sigCopyProgress(++m_FilesToCopyCount);
        }
        else
        {
            emit sigCopyProgress(-1);
            return;
        }
    }
    else
    {

        // Folder copy.
        QDir destDir(dest);

        // Remove, if it exists.
        if (destDir.exists())
        {
            if ( !rmDir(destDir.path()) )
            {
                // Remove went wrong.
                emit sigCopyProgress(-1);

                // Shut up and go!
                return;
            }
        }

        //destDir.mkpath(".");
        destDir.mkdir(dest);

        QDir sourceDir(source);
        QStringList filesList = sourceDir.entryList(QDir::Files);
        QString fileName;

        foreach(fileName, filesList)
        {
            if ( QFile::copy(source + "//" + fileName, dest + "//" + fileName) )
            {
                int percentage = ++m_FilesToCopyCount;
                //qDebug() << "copyoverwrite progress: " << m_FilesToCopyCount << " size= " << filesList.size();
                emit sigCopyProgress(percentage);
            }
            else
            {
                emit sigCopyProgress(-1);
                return;
            }
        }
    }
}

void FileSystemManager::slotSearchInMusicCollection(QString path)
{
    qDebug() << "FileSystemManager::slotSearchInMusicCollection " << path;
    scanDirsToMusicCollection(QDir(path));
}

void FileSystemManager::slotSearchInFileIncoming(QString path)
{
    qDebug() << "FileSystemManager::slotSearchInFileIncoming " << path;
    scanDirsToUpdateCollection(QDir(path));
}

void FileSystemManager::slotCompareFlacLists()
{
    qDebug() << "FileSystemManager::slotCompareFlacLists";
    compareFlacLists();
}

void FileSystemManager::slotRemoveDir(const QString &dirName)
{
    qDebug() << "FileSystemManager::slotRemoveDir " << dirName;
    rmDir(dirName);
}


// This is a overwrite-copy!
void FileSystemManager::slotCopy(bool isFile, QString source, QString dest)
{
    copyOverwrite(isFile, source, dest);
}

// Main Comparison Algorithm.
void FileSystemManager::compareFlacLists()
{
    qDebug() << "FileSystemManager::compareFlacLists " << (m_DeepScanEnabled ? " deep-scan enabled" : " quickscan enabled");

    if ( m_pScannerUpdateCollection->getAlbumData().getAlbumList().empty())
    {
        qDebug() << "empty folders!!!\n";
        return;
    }

    m_DiffCollection.clear();
    bool duplicateFound=false;
    int count = 0;

    foreach(const Album& uA, m_pScannerUpdateCollection->getAlbumData().getAlbumList())
    {
        // Reset flag.
        duplicateFound = false;

        // Start Folder Comparison.

        foreach(const Album& mA,m_pScannerMusicCollection->getAlbumData().getAlbumList())
        {
            if (uA.getName() == mA.getName())
            {
                if ( !m_DeepScanEnabled )
                {
                    duplicateFound = true;
                    emit sigFlacFound( "duplicate found! " + uA.getName());
                }
                else
                {
                    // Compare Tracks and Md5 of two given Albums.
                    duplicateFound = isAlbumDuplicate(uA, mA);
                }
            }
        }

        if ((!duplicateFound) )
        {
            m_DiffCollection.push_back(uA);
            //qDebug() << QString::number(count) << " seems to be a new one...." << uIt->getPath();
            emit sigFlacFound( QString::number(count) + " update album found! " + uA.getName());
            //emit sigFolderFound(*uIt);
        }
    }
    emit sigFlacListComparisonFinished(m_DiffCollection);
    /*
    foreach(const Album& alb, m_DiffCollection)
    {
        if (m_DeepScanEnabled)
        {
            foreach(const FlacTrack& t, alb.getFlacTrackList())
            {
                qDebug() << "FlacTrack: " << t.m_File.completeBaseName();
            }
        }

    }
*/
}

bool FileSystemManager::rmDir(const QString &dirName)
{
    bool result = true;
    QDir dir(dirName);
    //int cnt=0;

    if (dir.exists(dirName))
    {
        Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden  | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
        {
            if (info.isDir())
            {
                result = rmDir(info.absoluteFilePath());
                qDebug() << "rmDir-Counter: " << ++m_FilesToCopyCount;
                emit sigCopyProgress(m_FilesToCopyCount);
            }
            else
            {
                result = QFile::remove(info.absoluteFilePath());
                qDebug() << "rmDir-Counter: " << ++m_FilesToCopyCount;
                emit sigCopyProgress(m_FilesToCopyCount);
            }

            if (!result)
            {
                emit sigCopyProgress(-1);
                return result;
            }

        }
        result = dir.rmdir(dirName);
    }

    return result;
}

bool FileSystemManager::isAlbumDuplicate(const Album &updateAlbum, const Album &collAlbum)
{
    bool duplicateFound = false;
    if ( updateAlbum.getFlacTrackList().size() == collAlbum.getFlacTrackList().size() )
    {
        Utils utl;
        duplicateFound = utl.compareVectorOfFlacTracks(updateAlbum.getFlacTrackStrList(), collAlbum.getFlacTrackStrList());
    }
    else
    {
        duplicateFound = false;
    }
    return duplicateFound;
}

QString FileSystemManager::getLastPartFromPath(const QString& inPath)
{
    QFileInfo fi(inPath);
    QStringList dotParts = fi.absoluteFilePath().split("/");
    QString part="";
    if ( !dotParts.isEmpty() && (dotParts.size() > 0) )
    {
        part = dotParts[dotParts.size()-1];
        qDebug() << "FileSystemManager::getLastPartFromPath " << part << " size" << dotParts.size();
    }
    return part;
}

QString FileSystemManager::getSubFolderPart(const QString inPath)
{
    QFileInfo fi(inPath);
    QStringList dotParts = fi.absoluteFilePath().split("/");
    QString part="";
    if ( !dotParts.isEmpty() && (dotParts.size()> 1))
    {
        part = dotParts[dotParts.size()-2];
    }
    qDebug() << "FileSystemManager::getSubFolderPart " << part;
    return part;
}

void FileSystemManager::scanDirsToMusicCollection(const QDir &dir)
{
    if ( NULL != m_pScannerMusicCollection )
        delete m_pScannerMusicCollection;

    m_pScannerMusicCollection= new ThreadFlacScanner(dir);
    connect(this, SIGNAL(sigStopScanner()), m_pScannerMusicCollection, SLOT(slotStop()));
    connect(m_pScannerMusicCollection, SIGNAL(sigFlacSearchFinished()), this, SIGNAL(sigSearchInMusicCollectionFinished()));
    connect(m_pScannerMusicCollection, SIGNAL(sigAlbumFound(QString)), this, SIGNAL(sigFlacFound(QString)));
    connect(this, SIGNAL(sigEnableDeepScan(bool)), m_pScannerMusicCollection, SLOT(slotDeepScanEnabled(bool)));
    m_pScannerMusicCollection->start();
}

void FileSystemManager::scanDirsToUpdateCollection(const QDir &dir)
{
    if ( NULL != m_pScannerUpdateCollection )
        delete m_pScannerUpdateCollection;

    m_pScannerUpdateCollection= new ThreadFlacScanner(dir);
    connect(this, SIGNAL(sigStopScanner()), m_pScannerUpdateCollection, SLOT(slotStop()));
    connect(m_pScannerUpdateCollection, SIGNAL(sigFlacSearchFinished()), this, SIGNAL(sigSearchInFileIncomingFinished()));
    connect(m_pScannerUpdateCollection, SIGNAL(sigAlbumFound(QString)), this, SIGNAL(sigFlacFound(QString)));
    connect(this, SIGNAL(sigEnableDeepScan(bool)), m_pScannerUpdateCollection, SLOT(slotDeepScanEnabled(bool)));
    m_pScannerUpdateCollection->start();
}


void FileSystemManager::slotCopyAllFolderTo( QStringList srcPaths, QStringList destPath)
{
    qDebug() << "FileSystemManager::slotCopyAllFolderTo()";

    // Reset File Counter.
    m_FilesToCopyCount = 0;

    // Copy files or folders.
    for ( int i =0; i< srcPaths.size(); ++i )
    {
        // TODO: put in name filters
        if ( srcPaths[i].endsWith(".flac") )
        {
            copyOverwrite(true, srcPaths[i], destPath[i]);
        }
        else
        {
            copyOverwrite(false, srcPaths[i], destPath[i]);
        }
    }
}

void FileSystemManager::slotResetFileCounter()
{
    m_FilesToCopyCount = 0;
}

void FileSystemManager::slotEnableDeepScan(bool enable)
{
    qDebug() << "FileSystemManager::slotEnableDeepScan: " << enable;
    m_DeepScanEnabled = enable;
    emit sigEnableDeepScan(enable);
}

void FileSystemManager::slotInitOfMusicCollectionModelFinished()
{
    qDebug() << "FileSystemManager::slotInitOfAlbumModelFinished()";
    emit sigSearchInMusicCollectionFinished();
}

void FileSystemManager::slotInitOfUpdateCollectionModelFinished()
{
    qDebug() << "FileSystemManager::slotInitOfUpdateCollectionModelFinished()";
    emit sigSearchInFileIncomingFinished();
}

/*
void FileSystemManager::slotStopScanMusicCollection()
{
    qDebug() << "FileSystemManager::slotStopScanMusicCollection";
}

void FileSystemManager::slotStopScanUpdateCollection()
{
    qDebug() << "FileSystemManager::slotStopScanUpdateCollection";
    m_RequestStopScanDirs = true;
}
*/
